﻿namespace Pottery.Module.Infrastructure.Models
{
    using System;
    using System.Data.SqlTypes;
    using System.Runtime.Serialization;
    using System.Text.RegularExpressions;
    using Pottery.Model.Infrastructure;

    /// <summary>
    /// Employee
    /// </summary>
    [DataContract]
    public class Employee : Human, IValidatable, IAssignable, IEquatable<Employee>
    {
        #region Constructors

        /// <summary>
        /// Initializes new Employee with default params.
        /// </summary>
        public Employee() : base() { }

        /// <summary>
        /// Initializes new Employee with params.
        /// </summary>
        /// <param name="id">Employee ID</param>
        /// <param name="firstName">First name</param>
        /// <param name="lastName">Last name</param>
        /// <param name="login">Login in system</param>
        /// <param name="password">Password in system</param>
        /// <param name="email">Email</param>
        /// <param name="position">Employee role in system.</param>
        public Employee(string firstName, string lastName, string login, string password,
            string email, Enumerators.EmployeeStatus position, double salary)
            : this(firstName, lastName, login, password, email, string.Empty, string.Empty, null, position, salary) { }


        /// <summary>
        /// Initializes new Employee with params.
        /// </summary>
        /// <param name="id">Employee ID</param>
        /// <param name="firstName">First name</param>
        /// <param name="lastName">Last name</param>
        /// <param name="login">Login in system</param>
        /// <param name="password">Password in system</param>
        /// <param name="email">Email</param>
        /// <param name="phone">Phone</param>
        /// <param name="position">Employee role in system.</param>
        public Employee(string firstName, string lastName, string login, string password,
            string email, string phone, string address, byte[] photo, Enumerators.EmployeeStatus position, double salary)
            : base(login, password, firstName, lastName, email, address, phone, photo)
        {
            Salary = salary;
            Position = position;
        }


        #endregion

        #region Properties

        /// <summary>
        /// Salary
        /// </summary>
        [DataMember(Order = 2)]
        public double Salary
        {
            get { return m_Salary; }
            set
            {
                m_Salary = value;
            }
        }

        /// <summary>
        /// Status
        /// </summary>
        [DataMember(Order = 1)]
        public Enumerators.EmployeeStatus Position
        {
            get { return m_Position; }
            set
            {
                m_Position = value;
            }
        }

        #endregion

        #region IValidatable implementation

        /// <summary>
        /// Checks instance for data`s validity
        /// </summary>
        /// <returns>checking result</returns>
        public bool Validate()
        {
            bool result = true;

            if (string.IsNullOrEmpty(Login) || string.IsNullOrWhiteSpace(Login))
                result = false;

            if (Login.Length < ModelConstants.MIN_LOGIN_LENGTH || Login.Length > ModelConstants.MAX_LOGIN_LENGTH)
                result = false;

            if (Login.Contains(ModelConstants.SPACE))
                result = false;

            if (string.IsNullOrEmpty(FirstName) || string.IsNullOrWhiteSpace(FirstName))
                result = false;

            if (FirstName.Length > ModelConstants.MAX_FIRST_NAME_LENGTH)
                result = false;

            if (FirstName.Contains(ModelConstants.SPACE))
                result = false;

            if (string.IsNullOrEmpty(LastName) || string.IsNullOrWhiteSpace(LastName))
                result = false;

            if (LastName.Length > ModelConstants.MAX_LAST_NAME_LENGTH)
                result = false;

            if (LastName.Contains(ModelConstants.SPACE))
                result = false;

            if (string.IsNullOrEmpty(Password) || string.IsNullOrWhiteSpace(Password))
                result = false;

            if (Password.Length < ModelConstants.MIN_PASSWORD_LENGTH || Password.Length > ModelConstants.MAX_PASSWORD_LENGTH)
                result = false;

            if (Password.Contains(ModelConstants.SPACE))
                result = false;

            if (!Regex.IsMatch(Email, ModelConstants.EMAIL_REGULAR_EXPRESSION))
                result = false;

            if (Email.Length > ModelConstants.MAX_EMAIL_LENGTH)
                result = false;

            if (Phone != null && Phone.Length > ModelConstants.MAX_PHONE_LENGTH)
                result = false;

            return result;
        }

        #endregion

        #region IAssignable implementation

        /// <summary>
        /// Copy data from current object to object in param.
        /// </summary>
        /// <param name="obj">object to change </param>
        public void AssignTo(object obj)
        {
            if (obj == null)
                throw new ArgumentNullException("obj");

            if (obj is Employee)
            {
                Employee empl = obj as Employee;
                empl.FirstName = FirstName;
                empl.LastName = LastName;
                empl.Login = Login;
                empl.Password = Password;
                empl.Email = Email;
                empl.Phone = Phone;
                empl.Address = Address;
                empl.Photo = Photo;
                empl.Position = m_Position;
                empl.Salary = m_Salary;

                return;
            }

            throw new NotSupportedException("Not supported type!");
        }

        #endregion

        #region IEquatable<Employee> Implementation

        /// <summary>
        /// TODO:Description
        /// </summary>
        /// <param name="other">TODO:Description</param>
        /// <returns>TODO:Description</returns>
        public bool Equals(Employee other)
        {
            if (!Login.Equals(other.Login))
                return false;

            return true;
        }

        #endregion

        #region Private Fields

        private double m_Salary = default(double);
        private Enumerators.EmployeeStatus m_Position = Enumerators.EmployeeStatus.Worker;


        #endregion
    }
}
